package ci.web.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.nio.file.Files;
import java.util.Properties;
import java.util.Set;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.util.TypeUtils;

import ci.web.CiConfig;
import io.netty.util.internal.logging.InternalLoggerFactory;

/**
 * json/properties与config-java-bean之间转换
 * @author zhh
 */
public class ConfigUtil {

    /**
     * 将obj转换为java_bean
     * @param obj
     * @param clazz
     * @return
     */
    public static <T> T cast(JSONObject obj, Class<T> clazz){
        T instance;
        try {
            instance = clazz.newInstance();
        } catch (Exception e) {
            InternalLoggerFactory.getInstance(CiConfig.class).error("Coud't Instance:"+clazz.getName());
            return null;
        }
        Field[] fields = clazz.getDeclaredFields();
        for(String key : obj.keySet()){
            Field field = null;
            try{
                field = clazz.getDeclaredField(key);
            }catch(NoSuchFieldException nferr){
                for(Field tmpField:fields){
                    if(tmpField.getName().equalsIgnoreCase(key)){
                        field = tmpField;
                    }
                }
            }
            if(field != null && isInstanceField(field)){
                try{
                	field.setAccessible(true);
                	field.set(instance, TypeUtils.cast(obj.get(key), field.getType(), ParserConfig.getGlobalInstance()));
                }catch(Exception setErr){
                    //ignore
                }
            }
        }
        return instance;
    }
    /**
     * 将javabean实例转为JSONObject<br/>
     * 不支持多层javabean嵌套
     * @param bean
     * @return
     */
    public static JSONObject toJson(Object bean){
        if(bean instanceof JSONObject){
            return (JSONObject)bean;
        }
        JSONObject obj = new JSONObject();
        Class<?> clazz = bean.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for(Field field : fields){
            if(isInstanceField(field)){
                try {
                    field.setAccessible(true);
                    obj.put(field.getName(), field.get(bean));
                } catch (IllegalArgumentException | IllegalAccessException e) {
                    // ignore
                }
            }
        }
        return obj;
    }
    
    /**
     * 将javabean实例转为Properties<br/>
     * 不支持多层javabean嵌套
     * @param bean
     * @return
     */
    public static Properties toProperties(Object bean){
        JSONObject obj = toJson(bean);
        Properties p = new Properties();
        Set<String> ks = obj.keySet();
        for(String key : ks){
        	String v = obj.getString(key);
            p.put(key, v==null ? "":v);
        }
        return p;
    }
    /**
     * 加载json/properties文件, 并读取为Properties
     * @param file
     * @return
     */
    public static Properties loadAsProperties(String file){
        JSONObject obj = loadAsJson(file);
        if(obj != null){
            Properties p = new Properties();
            Set<String> ks = obj.keySet();
            for(String key : ks){
            	Object v = obj.get(key);
            	if(v==null || v.equals("")){
            		continue;
            	}
                p.put(key, v);
            }
            return p;
        }
        return null;
    }
    /**
     * 加载json/properties文件, 并读取为JSONObject
     * @param file
     * @return
     */
    public static JSONObject loadAsJson(String file){
        try{
            String str = null;
            File tmpFile = new File(file);
            if(tmpFile.exists()==false){
                URL url = Thread.currentThread().getContextClassLoader().getResource(file);
                if (url == null) {
                    url = CiConfig.class.getResource(file);
                }
                if(url == null){
                    throw new IOException(file);
                }
                tmpFile = new File(url.getFile());
                if(file.endsWith(".json")){
                    str = new String(Files.readAllBytes(tmpFile.toPath()));
                }else{
                    Properties p = new Properties();
                    try(FileInputStream fi = new FileInputStream(tmpFile)){
                        p.load(fi);
                    }
                    str = JSON.toJSONString(p);
                }
            }
            if(file.endsWith(".json")){
                str = new String(Files.readAllBytes(tmpFile.toPath()));
            }else{
                Properties p = new Properties();
                try(FileInputStream fi = new FileInputStream(tmpFile)){
                    p.load(fi);
                }
                str = JSON.toJSONString(p);
            }
            return JSON.parseObject(str);
        }catch(Exception err){
            if(err instanceof IOException){
                err = new IOException(file+" LoadFailed!");
            }
            InternalLoggerFactory.getInstance(CiConfig.class).error(err);
            return null;
        }
    }

    private static boolean isInstanceField(Field field){
        int mod = field.getModifiers();
        return Modifier.isStatic(mod)==false && 
                Modifier.isFinal(mod)==false;
    }
}
